#region Using directives
using System;
using Microsoft.DirectX.Direct3D;
using SharpWind;
using SharpWind.Graphics.Settings;
using System.Drawing;
using Microsoft.DirectX;
using SharpWind.Math;
using Texture = SharpWind.Resources.Textures.Texture;
#endregion

namespace SharpWind.Graphics
{
	public class GraphicsDevice : IDisposable
	{
		#region Fields

		private Device device = null;

		private Sprite sprite = null;

		private SharpWind.Settings settings = SharpWind.Settings.Default;

		private int currentBackBuffer = 0;

		#endregion

		#region Methods

		internal bool Initialize( SharpWind.Settings settings )
		{
			Microsoft.DirectX.Direct3D.DisplayMode displayMode = GraphicsDeviceEnumerator.DisplayModeFromSettings( settings );

			PresentParameters presentParams			= new PresentParameters();
			if( !settings.Windowed )
			{
				presentParams.BackBufferWidth			= displayMode.Width;
				presentParams.BackBufferHeight			= displayMode.Height;
				presentParams.BackBufferFormat			= displayMode.Format;
				presentParams.BackBufferCount			= settings.BackBuffers;
				presentParams.FullScreenRefreshRateInHz = settings.RefreshRate;
				presentParams.PresentationInterval		= ( settings.VSync ) ? PresentInterval.One : PresentInterval.Immediate;
			}

			presentParams.SwapEffect				= SwapEffect.Discard;
			presentParams.Windowed					= settings.Windowed;
			presentParams.EnableAutoDepthStencil	= true;
			presentParams.AutoDepthStencilFormat	= DepthFormat.D16;


			CreateFlags flags = CreateFlags.SoftwareVertexProcessing;
			Caps caps = Manager.GetDeviceCaps( 0, DeviceType.Hardware );

			if( caps.DeviceCaps.SupportsHardwareTransformAndLight )
			{
				flags = CreateFlags.HardwareVertexProcessing;
			}

			if( caps.DeviceCaps.SupportsPureDevice )
			{
				//flags |= CreateFlags.PureDevice;
			}

			try
			{
				this.device = new Device( 0, DeviceType.Hardware, Engine.Instance.Window, flags, presentParams );
				this.device.DeviceReset += new EventHandler( device_DeviceReset );
				device_DeviceReset( this.device, EventArgs.Empty );

				this.currentBackBuffer = 0;

				this.sprite = new Sprite( this.device );
			}
			catch
			{
				return false;
			}

			return true;
		}

		private void device_DeviceReset( object sender, EventArgs e )
		{
			Device device = sender as Device;
			if( device != null )
			{

			}
		}

		public void BeginRender()
		{
			this.device.Clear( ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1f, 0 );
			this.device.BeginScene();
		}

		public void EndRender()
		{
			this.device.EndScene();
			this.device.Present();

			if( ++this.currentBackBuffer == this.settings.BackBuffers + 1 )
			{
				this.currentBackBuffer = 0;
			}
		}

		public void SetTexture( int stage, Texture texture )
		{
			if( texture != null )
			{
				this.device.SetTexture( stage, texture.DxTexture );
			}
			else
			{
				this.Device.SetTexture( stage, null );
			}
		}

		public void Dispose()
		{
			if( this.sprite != null )
			{
				this.sprite.Dispose();
				this.sprite = null;
			}

			if( this.device != null )
			{
				this.device.Dispose();
				this.device = null;
			}
		}

		#endregion

		#region Properties

		public bool Fog
		{
			get
			{
				return this.device.RenderState.FogEnable;
			}
			set
			{
				this.device.RenderState.FogEnable = value;
			}
		}

		public bool Lighting
		{
			get
			{
				return this.device.RenderState.Lighting;
			}
			set
			{
				this.device.RenderState.Lighting = value;
			}
		}

		public Matrix ViewMatrix
		{
			get
			{
				return this.device.Transform.View;
			}
			set
			{
				this.device.Transform.View = value;
			}
		}

		public Matrix ProjectionMatrix
		{
			get
			{
				return this.device.Transform.Projection;
			}
			set
			{
				this.device.Transform.Projection = value;
			}
		}

		public Matrix WorldMatrix
		{
			get
			{
				return this.device.Transform.World;
			}
			set
			{
				this.device.Transform.World = value;
			}
		}

		public Material Material
		{
			get
			{
				return this.device.Material;
			}
			set
			{
				this.device.Material = value;
			}
		}

		public VertexFormats VertexFormat
		{
			get
			{
				return this.device.VertexFormat;
			}
			set
			{
				this.device.VertexFormat = value;
			}
		}

		public Device Device
		{
			get
			{
				return this.device;
			}
		}

		internal Sprite Sprite
		{
			get
			{
				return this.sprite;
			}
		}

		#endregion
	}
}
